package utils

import (
	"bytes"
	"crypto/rsa"
	"crypto/sha1"
	"crypto/sha256"
	"crypto/sha512"
	"crypto/x509"
	"encoding/binary"
	"errors"
	"golang.org/x/crypto/pkcs12"
	"hash"
	"io/ioutil"
)

// ReadPrivateKey 根据密文获取私钥
func ReadPrivateKey(filename, password string) (*rsa.PrivateKey, int64, error) {
	var (
		pfxData []byte
		keys    []interface{}
		certs   []*x509.Certificate
		err     error
	)
	//log.Println(filename)
	if pfxData, err = ioutil.ReadFile(filename); err != nil {
		//log.Println(err)
		return nil, 0, err
	}
	keys, certs, err = pkcs12.DecodeAll(pfxData, password)
	if err != nil {
		//log.Print(err)
		return nil, 0, err
	}
	if keys != nil {
		privateKey := keys[0].(*rsa.PrivateKey)
		if err = privateKey.Validate(); err != nil {
			return nil, 0, err
		}
		if certs == nil {
			return nil, 0, errors.New("未获取到证书")
		}
		return privateKey, certs[0].SerialNumber.Int64(), nil
	}
	return nil, 0, errors.New("获取密钥失败")
}

// getDataHash 计算数据校验返回hash值
func getDataHash(data []byte, timestamp int64, method string) []byte {
	var hash hash.Hash
	switch method {
	case "1.0.0.e1":
		hash = sha1.New()
	case "1.0.0.e2":
		hash = sha256.New()
	case "1.0.0.e3":
		hash = sha512.New()
	default:
		hash = sha256.New()
	}
	buf := bytes.NewBuffer(data)
	// 大端写入时间戳
	binary.Write(buf, binary.BigEndian, timestamp)
	// 计算校验和
	hash.Write(buf.Bytes())
	return hash.Sum(nil)
}
